﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using MySql.Data.MySqlClient;
using YmtAuth.Domain.Model.BlacklistUser;
using YmtAuth.Domain.Model.Safe;
using YmtAuth.Domain.Repository;
using YmtSystem.CrossCutting;
using YmtAuth.Common;

namespace YmtAuth.Repository.MySQL
{
    public class UserLoginIpCountEntityRepository : MySQLRepository<UserLoginIpCountEntity>,
        IUserLoginIpCountEntityRepository
    {
        public UserLoginIpCountEntityRepository()
            : base(ConfigurationManager.AppSettings["LoginIpCountInfo_MySQLConnString"], "LoginIpCountInfo")
        {

        }
        //获取登录IP计数
        public int GetUserLoginIpCount(string ip, int minute, string userType, bool? loginSuccess = null)
        {
            string selectSQL = "";
            DynamicParameters selectPar;
            var loginIpCountTable = YmatouBlacklistUserSpecifications.GetLoginIpCounInfoTableName(userType);
            if (loginSuccess != null)
            {
                selectSQL =
                    string.Format("select LoginCount from {0} where Ip=@Ip AND LoginSuccess=@LoginSuccess AND (CountBeginTime between date_format(date_add(now(), interval @minute2 minute),'%Y-%m-%d %H:%i:%s') AND now())", loginIpCountTable);
                selectPar =
                    this.Parameters.AddString("@Ip", ip)
                        .AddInt("@minute2", minute)                         
                        .AddByte("@LoginSuccess", UserLoginIpCountEntity.IsSuccess(loginSuccess.Value))                        
                        .Build();
            }
            else
            {
                selectSQL =
                    string.Format("select LoginCount from {0} where Ip=@Ip AND (CountBeginTime between date_format(date_add(now(), interval @minute2 minute),'%Y-%m-%d %H:%i:%s') AND now())", loginIpCountTable);
                selectPar = this.Parameters.AddString("@Ip", ip)
                             .AddInt("@minute2", minute)                              
                             .Build();
            }
            var ipCountListInfo = Enumerable.Empty<int>();
            try
            {
                using (var conn = new MySqlConnection(ConfigurationManager.AppSettings["LoginIpCountInfo_MySQLConnString"]))
                {
                    ipCountListInfo = conn.Query<int>(selectSQL, selectPar, commandType: CommandType.Text, commandTimeout: ConfigUtility.LoginSafeSQLCommandTimeOut);
                }
            }
            catch (Exception ex)
            {
                YmatouLoggingService.Error(
                    "[GetUserLoginIpCount] mysql exception ip:{0},minute:{1},{2}", ip,
                    minute, ex.ToString());
            }
            return ipCountListInfo.Sum();
        }

        public int AddUserLoginIpCount(string loginIp, int minute, bool loginSuccess, string userType)
        {
            var insertPar = this.Parameters.AddString("@Ip", loginIp)
                            .AddInt("@AddMinute", minute)
                            .AddByte("@LoginSuccess", UserLoginIpCountEntity.IsSuccess(loginSuccess))                            
                            .Build();
            var loginIpCountTable = YmatouBlacklistUserSpecifications.GetLoginIpCounInfoTableName(userType);
            var insertSql =
                string.Format("insert {0} (Ip,CountEndTime,CountBeginTime,LoginCount,LastUpdateTime,LoginSuccess) Values (@Ip,date_format(date_add(now(), interval @AddMinute minute),'%Y-%m-%d %H:%i'),now(),1,now(),@LoginSuccess)", loginIpCountTable);
            var updateSQL =
                string.Format("update {0} set LoginCount=LoginCount+1,LastUpdateTime=now() where Ip=@Ip AND CountEndTime=@CountEndTime AND LoginSuccess=@LoginSuccess",loginIpCountTable);
            var selectSQL =
                string.Format("select date_format(now(), '%Y-%m-%d %H:%i') as CountBeginTime,date_format(CountEndTime, '%Y-%m-%d %H:%i') as CountEndTime from {0} where Ip=@Ip AND LoginSuccess=@LoginSuccess order by {0}.CountBeginTime desc limit 1",loginIpCountTable);
            var selectPar =
                this.Parameters.AddString("@Ip", loginIp)
                    .AddByte("@LoginSuccess", UserLoginIpCountEntity.IsSuccess(loginSuccess))                   
                    .Build();
            using (var conn = new MySqlConnection(ConfigurationManager.AppSettings["LoginIpCountInfo_MySQLConnString"]))
            {
                var ipCountInfo =
                    conn.Query<UserLoginIpCountEntity>(selectSQL, selectPar, commandType: CommandType.Text)
                        .FirstOrDefault();
                if (ipCountInfo == null || ipCountInfo.CountBeginTime > ipCountInfo.CountEndTime)
                {
                    try
                    {
                        return conn.Execute(insertSql, insertPar, commandType: CommandType.Text, commandTimeout: ConfigUtility.LoginSafeSQLCommandTimeOut);
                    }
                    catch (MySqlException ex)
                    {
                        if (ex.Number == 1062)
                            return -1062;
                        else
                        {
                            YmatouLoggingService.Error("[AddUserLoginIpCount] mysql exception ip:{0},ex:{1}", loginIp,
                                ex.ToString());
                            return -ex.Number;
                        }
                    }
                }
                else
                {
                    var upPar =
                        this.Parameters.AddString("@Ip", loginIp)
                            .AddDateTime("@CountEndTime", ipCountInfo.CountEndTime)
                            .AddByte("@LoginSuccess", UserLoginIpCountEntity.IsSuccess(loginSuccess))                            
                            .Build();
                    return conn.Execute(updateSQL, upPar, commandType: CommandType.Text, commandTimeout: ConfigUtility.LoginSafeSQLCommandTimeOut);
                }
            }
        }

        public int CheckIsNeedCountIp(string loginIp, string loginId, int minute, bool loginSuccess, string userType)
        {
            var insertPar =
                this.Parameters.AddString("@ip", loginIp)
                    .AddString("@loginId", loginId)
                    .AddInt("@addminute", minute)
                    .AddByte("@LoginSuccess", UserLoginIpCountEntity.IsSuccess(loginSuccess))                   
                    .Build();
            var loginIpCountListTable = YmatouBlacklistUserSpecifications.GetLoginIpCountListTableName(userType);
            //IP登录记录表
            var insertSql =
                string.Format("insert {0} (Ip,LoginId,CountTimeStart,CountTimeEnd,LoginSuccess) values(@ip,@loginId,now(),date_format(date_add(now(), interval @addminute minute),'%Y-%m-%d %H:%i'),@LoginSuccess)", loginIpCountListTable);
            //
            var ipCountListInfoSelectPar =
                this.Parameters.AddString("@Ip", loginIp)
                    .AddString("@loginId", loginId)
                    .AddByte("@LoginSuccess", UserLoginIpCountEntity.IsSuccess(loginSuccess))                    
                    .Build();
            var ipCountListInfoSelectSQL =
                string.Format("select date_format(now(),'%Y-%m-%d %H:%i') as CountTimeStart,date_format(CountTimeEnd, '%Y-%m-%d %H:%i') as CountTimeEnd from {0} where Ip=@Ip AND LoginId=@loginId AND LoginSuccess=@LoginSuccess order by {0}.CountTimeStart desc limit 1",loginIpCountListTable);
            using (var conn = new MySqlConnection(ConfigurationManager.AppSettings["LoginIpCountInfo_MySQLConnString"]))
            {
                var ipCountListInfo =
                    conn.Query<UserLoginIpCountEntity.UserLoginIpCountList>(ipCountListInfoSelectSQL,
                        ipCountListInfoSelectPar,
                        commandType: CommandType.Text, commandTimeout: ConfigUtility.LoginSafeSQLCommandTimeOut).FirstOrDefault();
                //用户登录IP不存在,或者不在结束时间范围内，则插入新记录
                if (ipCountListInfo == null || ipCountListInfo.CountTimeStart > ipCountListInfo.CountTimeEnd)
                {
                    try
                    {
                        return conn.Execute(insertSql, insertPar, commandTimeout: ConfigUtility.LoginSafeSQLCommandTimeOut, commandType: CommandType.Text);
                    }
                    catch (MySqlException ex)
                    {
                        if (ex.Number == 1062)
                            return -1062;
                        else
                        {
                            YmatouLoggingService.Error(
                                "[CheckIsNeedCountIp] mysql exception ip:{0},loginId:{1},minute:{2},loginSuccess:{3},ex:{4}",
                                loginIp,
                                loginId, minute, loginSuccess, ex.ToString());
                            return -ex.Number;
                        }
                    }
                }
            }
            return 0;
        }

        /// <summary>
        /// 重置最近统计周期的登录IP计数为0
        /// </summary>
        /// <param name="loginIp"></param>
        /// <param name="ipType"></param>
        /// <returns></returns>
        public int ResetLatestLoginIPCount(string loginIp, int ipType)
        {
            string tableName = string.Empty;
            int affectedRows = 0;
            if(ipType == 1)
            {
                tableName = "loginipcountinfo";
            }
            else{
                tableName = "loginipcountinfo_seller";
            }
            
            var par = this.Parameters.AddString("@ip", loginIp).Build();
            string updateSql = "UPDATE " + tableName + " set logincount=0 where Ip=@ip AND LoginSuccess in (1,0) order by LastUpdateTime desc limit 2";
            using (var conn = new MySqlConnection(this.connString))
            {
                affectedRows = conn.Execute(updateSql, par, commandTimeout: ConfigUtility.LoginSafeSQLCommandTimeOut);
            }

            YmatouLoggingService.Debug("重置最近统计周期的登录IP计数为0, ResetLatestLoginIPCount, loginIp: {0}, ipType: {1}, affectedRows: {2}", loginIp, ipType, affectedRows);

            return affectedRows;
        }
    }
}
